import {
  type ChangeEvent,
  type Dispatch,
  type FormEvent,
  type KeyboardEvent,
  type MouseEvent,
  type SetStateAction,
  useContext,
  useEffect,
  useState,
} from 'react';
import useToast from 'hooks/useToast';
import { useMutation } from '@tanstack/react-query';
import { clientUpdateUserBasicInfo } from '@/services/api';
import type { IContact, IDifference } from '@/interfaces';
import { nanoid } from 'nanoid';
import { UserIdPageContext } from '@/contexts/user-id';
import Spinner from '@/app/[locale]/component/spinner/spinner';
import Nodata from '@/app/[locale]/common/nodata/nodata';
import diff from 'microdiff';
import { getDiffData } from '@/lib/tool';

export default function UpdateBasicInfoUserIdPage() {
  const {
    source: { path },
    translatedFields,
  } = useContext(UserIdPageContext)!;
  const { show } = useToast();
  const [contacts, setContacts] = useState<IContact[]>(
    path.user?.details.contacts ?? [],
  );
  const [form, setForm] = useState<{
    personalizedSignature?: string;
    about?: string;
  }>({
    personalizedSignature: '',
    about: '',
  });
  const [isDisabledSave, setIsDisabledSave] = useState(true);
  const [differenceData, setDifferenceData] = useState<IDifference[]>([]);

  useEffect(() => {
    const diffData = diff(
      {
        personalizedSignature: path.user?.details.personalizedSignature ?? '',
        about: path.user?.details.about ?? '',
        contacts: path.user?.details.contacts ?? [],
      },
      {
        ...form,
        contacts,
      },
    );
    setDifferenceData(diffData);
    setIsDisabledSave(diffData.length === 0);
  }, [
    contacts,
    form,
    path.user?.details.about,
    path.user?.details.contacts,
    path.user?.details.personalizedSignature,
  ]);

  const clientUpdateUserBasicInfoMutation = useMutation(
    clientUpdateUserBasicInfo,
  );

  async function onSubmit(e: FormEvent<HTMLFormElement>) {
    try {
      e.stopPropagation();
      e.preventDefault();

      const data = getDiffData(differenceData);
      await clientUpdateUserBasicInfoMutation.mutateAsync({
        data,
      });

      setForm({ ...form, personalizedSignature: '', about: '' });
      show({
        type: 'SUCCESS',
        message: translatedFields.updateProfileCompleted,
      });
    } catch (e) {
      clientUpdateUserBasicInfoMutation.reset();
      show({
        type: 'DANGER',
        message: e,
      });
    }
  }

  function onChangeForm(
    e: ChangeEvent<HTMLInputElement | HTMLTextAreaElement>,
  ) {
    const name = e.target.name;
    const value = e.target.value;
    setForm({ ...form, [name]: value });
  }

  return (
    <form className="vstack gap-4" onSubmit={onSubmit}>
      <div>
        <label className="form-label">
          {translatedFields.personalSignature}
        </label>
        <input
          type="text"
          className="form-control"
          name="personalizedSignature"
          value={form.personalizedSignature}
          onChange={onChangeForm}
          aria-describedby="personalizedSignature"
        />
      </div>

      <div>
        <label className="form-label">{translatedFields.aboutMe}</label>
        <textarea
          rows={5}
          className="form-control"
          name="about"
          value={form.about}
          onChange={onChangeForm}
          aria-describedby="about"
        />
      </div>

      <div>
        <label className="form-label">
          {translatedFields.contactInformation}
        </label>
        <Contacts contacts={contacts} setContacts={setContacts} />
      </div>

      <button
        type="submit"
        disabled={clientUpdateUserBasicInfoMutation.isLoading || isDisabledSave}
        className="btn btn-outline-success col col-lg-2 my-4"
      >
        {clientUpdateUserBasicInfoMutation.isLoading && (
          <Spinner classs="me-2" />
        )}
        {translatedFields.updateProfile}
      </button>
    </form>
  );
}

const Contacts = ({
  contacts = [],
  setContacts,
}: {
  contacts: IContact[];
  setContacts: Dispatch<SetStateAction<IContact[]>>;
}) => {
  const [form, setForm] = useState<{
    key: string;
    val: string;
  }>({
    key: '',
    val: '',
  });
  const { show } = useToast();
  const { translatedFields } = useContext(UserIdPageContext)!;

  function onSubmit(
    e: MouseEvent<HTMLButtonElement> | KeyboardEvent<HTMLInputElement>,
  ) {
    e.stopPropagation();
    e.preventDefault();

    const { key, val } = form;
    if (!key || !val) {
      show({
        type: 'DANGER',
        message: translatedFields.enterNameOrContent,
      });
      return;
    }

    setContacts([...contacts, { id: nanoid(), key, val }]);
  }

  function onClickRemove(item: IContact) {
    setContacts([...contacts.filter((value) => value.id !== item.id)]);
  }

  function onChangeForm(e: ChangeEvent<HTMLInputElement>) {
    const name = e.target.name;
    const value = e.target.value;
    setForm({ ...form, [name]: value });
  }

  function handleKeyDown(e: KeyboardEvent<HTMLInputElement>) {
    if (e.key === 'Enter') {
      e.stopPropagation();
      e.preventDefault();
      onSubmit(e);
    }
  }

  return (
    <div className="card">
      <div className="card-body vstack gap-4">
        {contacts.length > 0 && (
          <div className="table-responsive">
            <table className="table table-borderless table-hover align-middle">
              <thead>
                <tr>
                  <th scope="col" className="text-nowrap">
                    {translatedFields.name}
                  </th>
                  <th scope="col" className="text-nowrap">
                    {translatedFields.content}
                  </th>
                  <th scope="col" className="text-nowrap"></th>
                </tr>
              </thead>
              <tbody>
                {contacts.map((item) => {
                  return (
                    <tr key={item.id}>
                      <td className="text-nowrap">{item.key}</td>
                      <td className="text-nowrap">{item.val}</td>
                      <td className="text-nowrap">
                        <button
                          type="button"
                          onClick={onClickRemove.bind(this, item)}
                          className="btn btn-outline-danger"
                        >
                          <i className="bi bi-dash-lg me-2"></i>
                          {translatedFields.remove}
                        </button>
                      </td>
                    </tr>
                  );
                })}
              </tbody>
            </table>
          </div>
        )}

        {contacts.length === 0 && <Nodata />}

        <div className="input-group my-4">
          <input
            type="text"
            className="form-control"
            name="key"
            value={form.key}
            onChange={onChangeForm}
            onKeyDown={handleKeyDown}
            aria-describedby="key"
            placeholder={translatedFields.enterNameExample}
          />
          <input
            type="text"
            className="form-control"
            name="val"
            value={form.val}
            onChange={onChangeForm}
            onKeyDown={handleKeyDown}
            aria-describedby="val"
            placeholder={translatedFields.enterContentExample}
          />
          <button
            type="button"
            onClick={onSubmit}
            className="btn btn-outline-primary"
          >
            <i className="bi bi-plus-lg me-2"></i>
            {translatedFields.add}
          </button>
        </div>
      </div>
    </div>
  );
};
